package com.projectframe.base.service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.projectframe.base.exception.BaseException;
import com.projectframe.base.report.PoiExcelReport;
import com.projectframe.base.utils.DateUtil;

public class PoiReportServiceImpl implements IPoiReportService 
{
	private static final Logger LOG = Logger.getLogger(PoiReportServiceImpl.class);
	
	private IReportFindDataService reportFindService;
	private String reportFilePath;
	private String reportUri;
	
	public IReportFindDataService getReportFindService() 
	{
		return reportFindService;
	}
	public void setReportFindService(final IReportFindDataService reportFindService) 
	{
		this.reportFindService = reportFindService;
	}
	public String getReportFilePath() 
	{
		return reportFilePath;
	}
	public void setReportFilePath(final String reportFilePath) 
	{
		this.reportFilePath = reportFilePath;
	}
	public String getReportUri() 
	{
		return reportUri;
	}
	public void setReportUri(final String reportUri) 
	{
		this.reportUri = reportUri;
	}
	
	/**
	 * 依查詢條件產生報表xls, 並回傳給用戶.
	 * 
	 * @param queryVo 查詢資料, queryVo的parms(Map型別)須設定下列參數:<br/>
	 * key = "userId", value = 使用者ID(於報表上顯示)<br/>
	 * key = "searchCriterion", value = Object[] searchList 內容為查詢條件, 型別為SearchCriterionRMIVO<br/>
	 * SearchCriterionRMIVO須依查詢條件設定下列<br/>
	 * fieldName = 設定欄位名稱<br/>
	 * operator = 設定比較條件, 例如: =, >, <, like等<br/>
	 * value = 設定條件值
	 * @param reportFilePrefix 報表檔案的Prefix, UseCase編號_UseCase中文名稱
	 * @param excelTemplateFile excel模版檔
	 * @param startDataRow 設定每一個sheet資料開始寫入的row number, excel的第一個row為0.
	 * @param functionType 製表查詢的類型, 如新增流程的預覽, 資料維護的製表, 或產出資料檔等
	 * @return 回傳結果, ResultRMIVO的設定值如下:<br/>
	 * 成功: status = 0, result = 傳址的url<br/>
	 * 失敗: status = -1, msgDesc = 訊息碼, message = 訊息內容
	 */
	public String reportProcess(final Map<String,?> params, final String reportFilePrefix, 
	                            final String excelTemplateFile, final int[] startDataRow, 
	                            final int functionType) 
	{
		return reportProcess(params, reportFilePrefix, excelTemplateFile, startDataRow, null,functionType);
	}
	
	/**
	 * 依查詢條件產生報表xls, 並回傳給用戶.
	 * 
	 * @param queryVo 查詢資料, queryVo的parms(Map型別)須設定下列參數:<br/>
	 * key = "userId", value = 使用者ID(於報表上顯示)<br/>
	 * key = "searchCriterion", value = Object[] searchList 內容為查詢條件, 型別為SearchCriterionRMIVO<br/>
	 * SearchCriterionRMIVO須依查詢條件設定下列<br/>
	 * fieldName = 設定欄位名稱<br/>
	 * operator = 設定比較條件, 例如: =, >, <, like等<br/>
	 * value = 設定條件值
	 * @param reportFilePrefix 報表檔案的Prefix, UseCase編號_UseCase中文名稱
	 * @param excelTemplateFile excel模版檔
	 * @param startDataRow 設定每一個sheet資料開始寫入的row number, excel的第一個row為0.
	 * @param headMap 設定每一個sheet的head, 所需替換的key/value.
	 * @param functionType 製表查詢的類型, 如新增流程的預覽, 資料維護的製表, 或產出資料檔等
	 * @return 回傳結果, ResultRMIVO的設定值如下:<br/>
	 * 成功: status = 0, result = 傳址的url<br/>
	 * 失敗: status = -1, msgDesc = 訊息碼, message = 訊息內容
	 */
	public String reportProcess(final Map<String,?> params, final String reportFilePrefix, 
	                            final String templateFilePath, final int[] startDataRow, 
	                            final Map<?,?>[] headMap, final int functionType) 
	{
		final String userId = (String)params.get("userId");
		String fileExtName = ".xls";
		
		final String fileName = reportFilePrefix + "_" + userId + "_" + DateUtil.getDateString(new Date(), DateUtil.pattern14) + fileExtName;
		final String outputFilePath = this.reportFilePath + fileName;
		
		//取得報表的最大筆數
		long maxCount = 60000;
		
		//取得report中所有sheet的資料
		final List<Object[]>[] modelListDatas = reportFindService.findReportData(params, functionType);
		
		//check the data size
		for (List<?> listData:modelListDatas) 
		{
			if (listData.size() > maxCount) 
			{
				LOG.error("The data count(" + listData.size() + ") is large than " + maxCount);
				final BaseException pos3ge = new BaseException("B312003");
				final String msg[] = {"" + maxCount};
				pos3ge.setArgs(msg);
				pos3ge.setStatus(-99);
				throw pos3ge;
			}
		}
		
		// 新增一個PoiExcelReport物件
		final PoiExcelReport excelReport = new PoiExcelReport(templateFilePath, outputFilePath, modelListDatas);
		excelReport.export(startDataRow, headMap);

		String urlFile = fileName;
		try 
		{
			urlFile = URLEncoder.encode(fileName, "UTF-8");
		} 
		catch (UnsupportedEncodingException e) 
		{}
		
		return reportUri + urlFile;
	}
}
